package com.bookstore.controller;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bookstore.entity.po.*;
import com.bookstore.entity.pojo.R;
import com.bookstore.entity.vo.BookTableVO;
import com.bookstore.entity.vo.OrderManageVO;
import com.bookstore.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@CrossOrigin
@RequestMapping("admin")
public class AdminController {
    @Autowired
    OrderService orderService;
    @Autowired
    UserService userService;
    @Autowired
    BookService bookService;
    @Autowired
    BookClassService bookClassService;
    @Autowired
    BookAuthorService bookAuthorService;
    @Autowired
    AuthorService authorService;

    @Autowired
    BookController bookController;

    @Value("${prop.upload-folder}")
    private String UPLOAD_FOLDER;


    @Value("${prop.IP}")
    private String IP;

    @GetMapping("orderList")
    public R getOrderList(Integer start ,Integer offset) {
        List<OrderManageVO> orderList = orderService.getOrderList(start,offset);
        return R.success(orderList);
    }

    @GetMapping("signedType")
    public R getOrderListByType (Integer type) {
        long count = orderService.count();

        List<OrderManageVO> orderList = orderService.getOrderList(0,Integer.parseInt(String.valueOf(count)));
        List<OrderManageVO> collect;

        if(type.equals(0)){
            collect  = orderList.stream().filter(v -> v.getSigned().equals(type) || v.getSigned().equals(1)).collect(Collectors.toList());
        }else {
            collect = orderList.stream().filter(v -> v.getSigned().equals(type)).collect(Collectors.toList());
        }

        return R.success(collect);
    }

    @PostMapping("shiped")
    public R shiped (@RequestBody Map<String,Object> params) {
        Integer id = (Integer) params.get("id");
        OrderPO orderPO = new OrderPO();
        orderPO.setId(id);
        orderPO.setSigned(OrderService._SHIPPED);
        orderPO.setLogistics(OrderService._SHIPPED_STRING);
        boolean b = orderService.updateById(orderPO);

        return b?R.success():R.error();
    }

    @PostMapping("cancel")
    public R cancel (@RequestBody Map<String,Object> params) {
        System.out.println(params);
        Integer id = (Integer) params.get("id");
        String userName = (String) params.get("userName");
        String  price =  params.get("price").toString();
        UserPO userPO = userService.getOne(new QueryWrapper<UserPO>().eq("user_name", userName));
        userPO.setMoney(userPO.getMoney() + Float.parseFloat(price));
        boolean update = userService.update(userPO, new QueryWrapper<UserPO>().eq("user_name", userName));
        if(!update){
            return R.error();
        }
        OrderPO orderPO = new OrderPO();
        orderPO.setId(id);
        orderPO.setSigned(OrderService.CANCEL);
        orderPO.setLogistics(OrderService.CANCEL_STRING);
        boolean b = orderService.updateById(orderPO);

        return b?R.success():R.error();
    }

    @GetMapping("count")
    public R count (){
        long count = orderService.count();
        return R.success(count);
    }
    @GetMapping("getUserList")
    public R getUserList (Integer start,Integer offset) {
        // 1 1 1
        //  3 3
        List<UserPO> list = userService.list();
        List<UserPO> userPOS;
        if(start + offset < list.size()){
             userPOS = list.subList(start, start +  offset);
        }else {
            userPOS = list.subList(start,start +  list.size() - start);
        }
        //JSON
        return R.success(userPOS);
    }

    @GetMapping("userCount")
    public R getUserCount () {
        long count = userService.count();
        return R.success(count);
    }

    @PostMapping("changeStatus")
    public R changeStatus (@RequestBody HashMap<String,Object> params) {
        String  userName = (String) params.get("userName");
        UserPO one = userService.getOne(new QueryWrapper<UserPO>().eq("user_name", userName));
        if( one == null){
            return R.error();
        }
        one.setStatus(one.getStatus() == 0? 1 : 0);

        boolean update = userService.update(one, new QueryWrapper<UserPO>().eq("user_name", userName));
        return update? R.success():R.error();
    }

    @GetMapping("findUserById")
    public R findUserById (String userName) {
        QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name",userName);
        List<UserPO> list = userService.list(queryWrapper);
        return R.success(list);
    }
    @PostMapping("confirmMoney")
    public R confirmMoney (@RequestBody HashMap<String,Object> params) {
        System.out.println(params);
        String money = params.get("money").toString();
        String userName = (String) params.get("userName");
        UserPO one = userService.getOne(new QueryWrapper<UserPO>().eq("user_Name", userName));
        if(one == null) {
            return R.error();
        }
        one.setMoney(one.getMoney() + Float.parseFloat(money));
        boolean update = userService.update(one, new QueryWrapper<UserPO>().eq("user_Name", userName));
        return update?R.success():R.error();
    }

    @GetMapping("getBookList")
    public R getBookList (Integer start,Integer offset ){
        List<BookTableVO> list = bookService.getList(start,offset);
        list.forEach(x -> {
            List<BookAuthorPo> bookAuthorPos = bookAuthorService.list(new QueryWrapper<BookAuthorPo>().eq("book_id", x.getId()));
            x.setAuthors(new ArrayList<>());
            bookAuthorPos.forEach(bookAuthorPo -> {
                AuthorPo authorPo = authorService.getById(bookAuthorPo.getAuthorId());
                x.getAuthors().add(authorPo);
            });

        });
        return R.success(list);
    }

    @GetMapping("bookCount")
    public R getBookCount () {
        return R.success(bookService.count());
    }

    @PostMapping("addBook")
    public R addBook (MultipartFile file,String bookName,Integer bookClass,String info,Float price,String publisher,String authorList) {

        int i = Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf(".");

        String originalFilename = file.getOriginalFilename();
        String prefex = originalFilename.substring(i, originalFilename.length());

        UUID uuid = UUID.randomUUID();

        System.out.println(uuid.toString());
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(UPLOAD_FOLDER + uuid.toString() + prefex);
            InputStream inputStream = file.getInputStream();
            byte[] b = new byte[inputStream.available()];
            inputStream.read(b);
            fileOutputStream.write(b);
            String s = IP +uuid.toString() + prefex;
            BookPO bookPO = new BookPO();
            bookPO.setBookName(bookName);
            bookPO.setPrice(price);
            bookPO.setClassId(bookClass);
            bookPO.setBookPic(s);
            bookPO.setInfor(info);
            bookPO.setPublisher(publisher);
            bookPO.setCreateTime(new Date());
            boolean save = bookService.save(bookPO);

            List<BookPO> list = bookService.list();
            BookPO bookPO1 = list.get(list.size() - 1);
            Integer id = bookPO1.getId();

            List<Integer> authors  = (List<Integer>) JSON.parse(authorList);
            authors.forEach(authorId -> {
                BookAuthorPo bookAuthorPo = new BookAuthorPo(id,authorId);
                bookAuthorService.save(bookAuthorPo);
            });
            System.out.println(authorList);
            return save?R.success():R.error();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.error();
    }
    @GetMapping("getBook")
    public R getBookById(Integer id) {

        //TODO 添加作者信息

        return bookController.selectOneById(id);
    }

    @PostMapping("update")
    public R update(@RequestBody BookPO bookPO) {

        Integer bookPOId = bookPO.getId();
        bookAuthorService.remove(new QueryWrapper<BookAuthorPo>().eq("book_id",bookPOId));
        bookPO.getAuthors().forEach(authorPo -> {
            BookAuthorPo bookAuthorPo = new BookAuthorPo(bookPOId,authorPo.getId());
            bookAuthorService.save(bookAuthorPo);
        });

        return bookService.updateById(bookPO)?R.success():R.error();
    }

    @PostMapping("changeBookPic")
    public R changeBookPic(MultipartFile file,Integer id) {
        BookPO byId = bookService.getById(id);
        //http://10.12.69.18:7529/img/c891353f-6fa9-4dab-ab21-1bed0460296d.png
        String bookPic = byId.getBookPic();
        int x = bookPic.lastIndexOf('/');
        String substring = bookPic.substring(x);
        File file1 = new File(UPLOAD_FOLDER + substring);
            boolean delete = file1.delete();

        int i = Objects.requireNonNull(file.getOriginalFilename()).lastIndexOf(".");

        String originalFilename = file.getOriginalFilename();
        String prefex = originalFilename.substring(i, originalFilename.length());

        UUID uuid = UUID.randomUUID();

        System.out.println(uuid.toString());
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(UPLOAD_FOLDER + uuid.toString() + prefex);
            InputStream inputStream = file.getInputStream();
            byte[] b = new byte[inputStream.available()];
            inputStream.read(b);
            fileOutputStream.write(b);
            String s = IP +uuid.toString() + prefex;
            BookPO bookPO = new BookPO();
            bookPO.setId(id);
            bookPO.setBookPic(s);
            boolean save = bookService.updateById(bookPO);
            return save?R.success():R.error();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
            return R.error();
    }

    @PostMapping("soldOut")
    public R soldOut (@RequestBody HashMap<String,Integer> params){
        Integer id = params.get("id");
        BookPO bookPO = bookService.getById(id);
        bookPO.setStatus(bookPO.getStatus() == BookService.ON_SALE ? BookService.NOT_ON_SALE : BookService.ON_SALE);
        boolean b = bookService.updateById(bookPO);
        return b?R.success():R.error();
    }
    @PostMapping("search")
    public R search (@RequestBody HashMap<String,String> params) {
        int classId = Integer.parseInt(params.get("classId"));
        int status = Integer.parseInt(params.get("status"));
        String bookName = params.get("bookName");
        String publisher = params.get("publisher");
        int authorId = Integer.parseInt(params.get("authorId"));
        QueryWrapper<BookClassOP> queryWrapper = new QueryWrapper<>();
        BookClassOP byId = bookClassService.getById(classId);
        List<BookTableVO> list = bookService.getList(0, Integer.parseInt(String.valueOf(bookService.count())));
        List<BookTableVO> bookTableVOStream = list;

        if(classId != -1){
            bookTableVOStream = list.stream().filter(v -> v.getClassName().equals(byId.getClassName())).collect(Collectors.toList());
        }
        if(status != 3) {
            bookTableVOStream = bookTableVOStream.stream().filter(v -> v.getStatus().equals(status)).collect(Collectors.toList());
        }
        bookTableVOStream = bookTableVOStream.stream().filter(v -> v.getBookName().contains(bookName)).collect(Collectors.toList());

        if(!publisher.equals("")){
            bookTableVOStream = bookTableVOStream.stream().filter( x -> x.getPublisher().contains(publisher)).collect(Collectors.toList());
        }
        if(authorId != -1) {

            List<BookAuthorPo> bookAuthorPos = bookAuthorService.list(new QueryWrapper<BookAuthorPo>().eq("auth_id", authorId));
            List<Integer> bookIds = bookAuthorPos.stream().map(BookAuthorPo::getBookId).collect(Collectors.toList());
            bookTableVOStream = bookTableVOStream.stream().filter(x -> bookIds.contains(x.getId())).collect(Collectors.toList());
        }
        bookTableVOStream.forEach(x -> {
            List<BookAuthorPo> bookAuthorPos = bookAuthorService.list(new QueryWrapper<BookAuthorPo>().eq("book_id", x.getId()));
            x.setAuthors(new ArrayList<>());
            bookAuthorPos.forEach(bookAuthorPo -> {
                AuthorPo authorPo = authorService.getById(bookAuthorPo.getAuthorId());
                x.getAuthors().add(authorPo);
            });

        });

        return R.success(bookTableVOStream);
    }
}
